// lexical analysis

// id -> Letter | Letter id
// digits -> digit digits | digit 
// OP-> +| - |* |/ |>| < | = | ( | ) | ; | ‘ | == | >= |<= | != 
// Keyword -> if | else | while | int | float
// Letter -> a|b|c|d|e|f|g|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z| _
// digit -> 0|1|2|3|4|5|6|7|8|9

/*
	input:srcinput.txt
	output:符号表和TOKEN串表
	g++ -o leicalAnalysis.exe lexicalAnalysis.cpp
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <cstring>
#include <ctype.h>
#include <fstream>
#include<iostream>
using namespace std;

struct table_item{
    char w_name[20];
    int w_kind;// 1 identifier 2 number const 
    int w_type;
    int w_val;
    int w_addr;
    struct table_item* item_next;
    table_item():w_kind(0), w_type(0),w_val(0),w_addr(0),item_next(nullptr) {}
    table_item(int addr) : w_kind(0), w_type(0),w_val(0),w_addr(addr),item_next(nullptr) {}
};

table_item *table_head,*table_tail,*table_p;

void add_item(table_item* item){
	table_p->item_next = item;
	table_p = table_p -> item_next;
	table_p -> item_next = nullptr;
}

bool find_item(char item[20]){
	table_item *p = table_head;
	while(p->item_next){
		p = p->item_next;
		if (strcmp(p->w_name,item)==0){
			return true;
		}
	}
	return false;
}
void outputSymbolTable(){
	ofstream outf;
	outf.open("SymbolTable.txt");
	table_item *p = table_head;
	while(p->item_next){
		p = p->item_next;
		outf << p->w_name <<' '<< p->w_kind << ' '<<p->w_type<<' '<<p->w_val<<' '<<p->w_addr<<endl;
	}
	outf.close();
}


int main(int argc, char const *argv[])
{
	// string s;
	ifstream inf;
	inf.open("srcinput.txt");
	ofstream tokenf;
	tokenf.open("token.txt");
    string s;
    char sentance_input[200];
    char word_token[20];
    char next_c;
    int w_forward=0,w_next=0;
    int w_state=0;
    int x_num=0,id_x=0;
    char w_keyword[][8]={"if","else","while","do","int","float","true","false"};
    int lenKeyword = 8;
    int addr = 0;

    table_head = new table_item();
    table_p = table_head;
    // table_p -> item_next = nullptr;
    // table_tail =new table_item;
    int lineNum = 0;
	while(getline(inf,s)){
		strcpy(sentance_input,s.c_str());
		lineNum++; // 行号加一
		// cout<<"要处理的字符串："<<s<<endl;
		w_next=0;
        w_forward=0;
        w_state=0;
        x_num=0;
        while(1){
        	switch(w_state){
        		case 0:
	                while((next_c=sentance_input[w_next])==' ' || next_c=='\t'){// || next_c=='\t'
	                    w_next++;
	                    w_forward++;
	                }
	                memset(word_token, 0x00, sizeof (char) * 20);
	        		// 判断为数字
	        		if (isdigit(next_c)){
	        			while( (next_c!=' ') && (isdigit(next_c))){
	        				w_next++;
	        				next_c = sentance_input[w_next];
	        			}
	        			if(next_c==' '||next_c=='\0'||next_c=='\t'||next_c=='\n'||next_c==';'||next_c==','||next_c==')'||
	        				next_c=='('||next_c=='='||next_c=='>'||next_c=='<'||next_c =='*'||next_c=='/'||next_c=='+'||
	        				next_c=='-'||next_c =='&'||next_c=='|'){
	                        w_next--;
	                        for(int i = 0;i<=w_next - w_forward;++i){
	                        	word_token[i] = sentance_input[i+w_forward];
	                        }
	                        w_next++;
	                        // 此时w_next为分割符号
	                        word_token[w_next- w_forward] = '\0';
	                        w_forward = w_next;
	                        printf("token is [ const digits ,%s]\n",word_token);
	                        tokenf<<"digits "<<word_token<<endl;
	        			}
	        			else{
	        				cout<<"ERROR AR line "<<lineNum<<", unrecognized number!"<<endl;
	        				// exit(0);
	        			}
	        			w_state=0;
	        			break;
	        		}
	        		// 判断为标识符
	        		if (isalpha(next_c)){
	        			while( (next_c!=' ') && (isalpha(next_c) || isalnum(next_c) || next_c=='_')){
	                        w_next++;
	                        next_c=sentance_input[w_next];
	                    }
	                    if(next_c==' ' || !(isalpha(next_c)))
	                        w_next--;
	                    for(int i = 0;i<=w_next - w_forward;++i){
	                     	word_token[i] = sentance_input[i+w_forward];
	                    }
	                    w_next++;
	                    word_token[w_next-w_forward] = '\0';
	                    w_forward = w_next;
	                    // 识别关键字
	                    bool flag = false;
	                    for(int i=0;i<lenKeyword;i++){
	                        if(strcmp(word_token,w_keyword[i])==0){
	                            flag = true;
	                            printf("token is [ keyword ,%s]\n",word_token);
	                            tokenf<<"keyword "<<word_token<<endl;
	                            break;
	                        }
	                    }
	                    if(!flag){
	                    	printf("token is [ id ,%s]\n",word_token);
	                    	tokenf<<"id "<<word_token<<endl;
	                    	if (!find_item(word_token)){
			                    table_item* item = new table_item(addr);//++
			                    strcpy(item->w_name,word_token);
			                    add_item(item);
	                        }
	                    }
						w_state=0;
						break;
	        		}
	                switch (next_c){
	                    case '<':w_state=1;break;
	                    case '=':w_state=5;break;
	                    case '>':w_state=6;break;
	                    case '+':w_state=9;break;
	                    case '-':w_state=10;break;
	                    case '*':w_state=11;break;
	                    case '/':w_state=12;break;
	                    case '(':w_state=13;break;
	                    case ')':w_state=14;break;
	                    case ';':w_state=15;break;
	                    case '\'':w_state=16;break;
	                    case '&':w_state=19;break;
	                    case '|':w_state=20;break;
                        case '!':w_state=25;break;
	                    case '\0':w_state=100;
	                              memset(sentance_input, 0x00, sizeof (char) * 200);
	                              break;
	                    default : printf("error at line %d!\n",lineNum);
	                    // exit(0);
	                }
	        		break;
            case 1:
                w_next++;
                next_c=sentance_input[w_next];
                switch (next_c){
                    case '=': w_state=2;
                        break;
                    case '>': w_state=3;
                        break;
                    default: w_state=4;
                        break;
                }
                break;
            case 2:
	            for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 3:
	            for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
          	case 4: // <
          		w_next--;// 回退指针
	            for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 5: // =
                w_next++;
                next_c=sentance_input[w_next];
                switch (next_c){
                    case '=': w_state=17; // == 识别
                        break;
                    default: w_state=18; // = 识别
                        break;
                }
                break;
            case 6:
                w_next++;
                next_c=sentance_input[w_next];
                switch (next_c){
                    case '=': w_state=7;break;
                    default: w_state=8;break;
                }
                break;
            case 7:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 8:
           	    w_next--;
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 9:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 10:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 11:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 12:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 13:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 14:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 15:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 16:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
                break;
            case 17: // ==识别
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
            	break;
            case 18:
            	w_next--;// 等于的识别
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
            	break;
            case 19:
                w_next++;
                next_c=sentance_input[w_next];
                switch (next_c){
                    case '&': w_state=21;break;
                    default: w_state=22;break;
                }
                break;
            case 20:
                w_next++;
                next_c=sentance_input[w_next];
                switch (next_c){
                    case '|': w_state=23;break;
                    default: w_state=24;break;
                }
                break;
            case 21:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
            	break;
            case 22: // &识别
            	w_next--;
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
            	break;
            case 23:
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
           		break;
            case 24:
            	w_next--;
            	for(int i = 0;i<=w_next - w_forward;++i){
	               	word_token[i] = sentance_input[i+w_forward];
	            }
	            w_next++;
	            word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
           		break;
            case 25:
                for(int i = 0;i<=w_next - w_forward;++i){
                    word_token[i] = sentance_input[i+w_forward];
                }
                w_next++;
                word_token[w_next-w_forward] = '\0';
                printf("token is [ op ,%s]\n",word_token);
                tokenf<<"op "<<word_token<<endl;
                w_state=0;
                w_forward=w_next;
        	case 100: w_state=100; break;
        	}
        	if (w_state==100) break;
        }
	}
	printf("token is [ op ,$]");
	tokenf<<"op $";
	inf.close();
	tokenf.close();
	outputSymbolTable();
	// outputToken();
	return 0;
}

/*
g++ -o leicalAnalysis.exe lexicalAnalysis.cpp
*/